package com.haibara.codesubmiteval.utils;

import com.haibara.codesubmiteval.constant.FileConstant;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * 文件操作工具类
 *
 * @Author: mengyu
 * @Date: 2025/2/5
 */
public class FileUtil {

    /**
     * 根据传入的文件名生成随机文件名
     *
     * @param fileName 传入文件名
     * @return 随机文件名
     */
    public static String generateRandomFileName(String fileName) {
        // 将随机UUID加在文件名前
        return UUID.randomUUID() + "-" + fileName;
    }


    /**
     * 移动文件到指定目录
     *
     * @param file     文件
     * @param path     目录
     * @param fileName 移动到目录后的文件名
     * @throws IOException 异常
     */
    public static void moveFileTo(MultipartFile file, String path, String fileName) throws IOException {
        Path uploadPath = Paths.get(path);
        // 如果目录不存在则创建目录
        if (!Files.exists(uploadPath)) {
            Files.createDirectories(uploadPath);
        }
        // 移动文件
        Path filePath = uploadPath.resolve(fileName);
        file.transferTo(filePath.toFile());
    }

    /**
     * 将originPath下的fileName文件移动到moveToPath
     *
     * @param originPath 原文件夹
     * @param fileName   文件名
     * @param moveToPath 目的文件夹
     */
    public static void moveFileTo(String originPath, String fileName, String moveToPath) throws IOException {
        Path moveToDir = Paths.get(moveToPath);
        Files.createDirectories(moveToDir);
        Path source = Paths.get(originPath, fileName);
        Path target = moveToDir.resolve(fileName);
        Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
    }

    /**
     * 将originPath下的fileNames文件移动到moveToPath
     *
     * @param originPath 原文件夹
     * @param fileNames  文件名列表
     * @param moveToPath 目的文件夹
     */
    public static void moveFileTo(String originPath, List<String> fileNames, String moveToPath) throws IOException {
        Path moveToDir = Paths.get(moveToPath);
        Files.createDirectories(moveToDir);
        fileNames.forEach(tempName -> {
            Path source = Paths.get(FileConstant.tempFilePath, tempName);
            Path target = moveToDir.resolve(tempName);
            try {
                Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                throw new RuntimeException("文件移动失败: " + tempName);
            }
        });
    }

    /**
     * 清空指定文件夹下的所有文件和子目录
     *
     * @param dirPath 文件夹路径（字符串形式）
     * @throws IOException 文件操作异常
     */
    public static void clearDirectory(String dirPath) throws IOException {
        Path path = Paths.get(dirPath);
        FileUtil.clearDirectory(path);
    }


    /**
     * 清空指定文件夹下的所有文件和子目录
     *
     * @param directoryPath 文件夹路径
     * @throws IOException 文件操作异常
     */
    public static void clearDirectory(Path directoryPath) throws IOException {
        // 检查路径是否存在且是一个目录
        if (!Files.exists(directoryPath)) {
            throw new IOException("文件夹不存在：" + directoryPath);
        }
        if (!Files.isDirectory(directoryPath)) {
            throw new IOException("路径不是文件夹：" + directoryPath);
        }
        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(directoryPath)) {
            for (Path path : directoryStream) {
                // 如果是文件，直接删除；如果是目录，递归删除
                if (Files.isDirectory(path)) {
                    // 递归删除子目录
                    clearDirectory(path);
                    // 删除空的子目录
                    Files.deleteIfExists(path);
                } else {
                    // 删除文件
                    Files.deleteIfExists(path);
                }
            }
        } catch (DirectoryIteratorException | IOException e) {
            throw new IOException("清空文件夹时出错：" + e.getMessage());
        }
    }


    /**
     * 删除指定文件夹下与指定文件名匹配的文件
     *
     * @param dirPath  文件夹路径
     * @param fileName 要删除的文件名
     */
    public static void deleteFileByName(String dirPath, String fileName) throws IOException {
        Path directoryPath = Paths.get(dirPath);
        if (!Files.exists(directoryPath)) {
            throw new IOException("文件夹不存在：" + directoryPath);
        }
        if (!Files.isDirectory(directoryPath)) {
            throw new IOException("文件夹不存在：" + directoryPath);
        }
        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(directoryPath)) {
            for (Path path : directoryStream) {
                // 提取文件名
                String name = path.getFileName().toString();
                // 如果文件名匹配则删除
                if (name.equals(fileName)) {
                    Files.delete(path);
                }
            }
        } catch (IOException | DirectoryIteratorException e) {
            throw new IOException("删除文件时出错：" + e.getMessage());
        }
    }

    /**
     * 比较两个文件内容是否相同
     *
     * @param file1Path 文件1路径
     * @param file1Name 文件1名
     * @param file2Path 文件2路径
     * @param file2Name 文件2名
     * @return 比较结果
     */
    public static boolean compareTwoFile(String file1Path, String file1Name, String file2Path, String file2Name) {
        Path path1 = Paths.get(file1Path, file1Name);
        Path path2 = Paths.get(file2Path, file2Name);
        boolean result;
        try {
            long mismatch = Files.mismatch(path1, path2);
            result = mismatch == -1;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 设置文件权限
     *
     * @param filePath    文件路径
     * @param permissions 权限
     */
    public static void setFilePermissions(String filePath, PosixFilePermission... permissions) {
        Path path = Paths.get(filePath);
        try {
            Set<PosixFilePermission> currentPerms =
                    Files.getPosixFilePermissions(path);
            // 移除所有权限
            currentPerms.remove(PosixFilePermission.OWNER_WRITE);
            currentPerms.remove(PosixFilePermission.GROUP_WRITE);
            currentPerms.remove(PosixFilePermission.OTHERS_WRITE);
            currentPerms.remove(PosixFilePermission.OWNER_READ);
            currentPerms.remove(PosixFilePermission.GROUP_READ);
            currentPerms.remove(PosixFilePermission.OTHERS_READ);
            currentPerms.remove(PosixFilePermission.OWNER_EXECUTE);
            currentPerms.remove(PosixFilePermission.GROUP_EXECUTE);
            currentPerms.remove(PosixFilePermission.OTHERS_EXECUTE);
            // 新增权限
            currentPerms.addAll(Arrays.asList(permissions));
            // 应用新权限
            Files.setPosixFilePermissions(path, currentPerms);
        } catch (IOException e) {
            throw new RuntimeException("权限更新失败", e);
        }
    }

    /**
     * 获取读权限，便于设置权限
     *
     * @return 读权限
     */
    public static PosixFilePermission[] getAllReadPermission() {
        return new PosixFilePermission[]{
                PosixFilePermission.OWNER_READ,
                PosixFilePermission.GROUP_READ,
                PosixFilePermission.OTHERS_READ,
        };
    }

    /**
     * 获取写权限，便于设置权限
     *
     * @return 写权限
     */
    public static PosixFilePermission[] getAllWritePermission() {
        return new PosixFilePermission[]{
                PosixFilePermission.OWNER_WRITE,
                PosixFilePermission.GROUP_WRITE,
                PosixFilePermission.OTHERS_WRITE,
        };
    }

    /**
     * 获取执行权限，便于设置权限
     *
     * @return 执行权限
     */
    public static PosixFilePermission[] getAllExecutePermission() {
        return new PosixFilePermission[]{
                PosixFilePermission.OWNER_EXECUTE,
                PosixFilePermission.GROUP_EXECUTE,
                PosixFilePermission.OTHERS_EXECUTE,
        };
    }

}
